package solutions.ferpa.ztest.ent;

import java.sql.*;
import java.util.ArrayList;
import br.com.telescope.adsrt.dom.*;
import br.com.telescope.adsrt.lib.*;
import br.com.telescope.t2.exception.Severity;

/**
 * API de persistência de dados da entidade OPERACOES_FUNCOES
 * @author Gerado pelo Telescope
 */
public class EntOperacoesFuncoes extends AssociativeEntity {
    
    public final static String ENTITY_NAME = "RTSYSINF.OPERACOES_FUNCOES";
    public final static String TABLE_NAME = "OPERACOES_FUNCOES";
    
    // <editor-fold defaultstate="collapsed" desc="Contrutores e inicializacao">
    /**
     * Construtores
     */
    public EntOperacoesFuncoes() {
        super();
        initialize();
    }
    
    public EntOperacoesFuncoes(BaseRuntime ctx) {
        super();
        initialize(ctx);
    }
    
    @Override
    public String getPrimaryKeyColumn() {
        return "ID";
    }
    
    @Override
    public void initialize(BaseRuntime ctx) {
        super.initialize(ctx);
        initialize();
    }
    
    public void initialize() {
        aFuncaoId = new DomId(this,"FUNCAO_ID", "Funcao"); 
        aFuncaoId.setRequired(true);
        oFuncaoId = new DomId();
        aId = new DomId(this,"ID", "Id"); 
        aId.setRequired(true);
        oId = new DomId();
        aOperacaoId = new DomId(this,"OPERACAO_ID", "Operação"); 
        aOperacaoId.setRequired(true);
        oOperacaoId = new DomId();
        ressetModified();
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Atributos da entidade">
    
    // Funcao
    private DomId aFuncaoId;
    private DomId oFuncaoId;
    
    // Id
    private DomId aId;
    private DomId oId;
    
    // Operação
    private DomId aOperacaoId;
    private DomId oOperacaoId;
    
    // <editor-fold defaultstate="collapsed" desc="Atributo FUNCAO_ID">
    
    public EntOperacoesFuncoes funcaoId(Long value) {
        setFuncaoId(value);
        return this;
    }
    
    public void setFuncaoId(DomId value) {
        if (value == null || value.isNull()) {
            nullifyFuncaoId();
        } else {
            aFuncaoId.setValue(value.getValue());
            if (aFuncaoId.isModified()) {
                setModified(true);
            }
        }
    }
    
    public void setFuncaoId(String value) {
        if (value == null) {
            nullifyFuncaoId();
        } else {
            aFuncaoId.setValue(value);
            if (aFuncaoId.isModified()) {
                setModified(true);
            }
        }
    }
    
    public void setFuncaoId(Long value) {
        aFuncaoId.setValue(value);
        if (aFuncaoId.isModified()) {
            setModified(true);
        }
    }
    
    public void setFuncaoId(Object value) {
        aFuncaoId.setValue(value);
        if (aFuncaoId.isModified()) {
            setModified(true);
        }
    }
    
    public void nullifyFuncaoId() {
        if (!aFuncaoId.isNull()) {
            aFuncaoId.setNull(true);
            setModified(true);
        }
    }
    
    public DomId getFuncaoId() {
        return aFuncaoId;
    }
    
    public DomId oldFuncaoId() {
        return oFuncaoId;
    }
    
    public Long valueOfFuncaoId() {
        return aFuncaoId.getValue();
    }
    
    public boolean isFuncaoIdModified() {
        return aFuncaoId.isModified();
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Atributo ID">
    
    public EntOperacoesFuncoes id(Long value) {
        setId(value);
        return this;
    }
    
    public void setId(DomId value) {
        if (value == null || value.isNull()) {
            nullifyId();
        } else {
            aId.setValue(value.getValue());
            if (aId.isModified()) {
                setModified(true);
            }
        }
    }
    
    public void setId(String value) {
        if (value == null) {
            nullifyId();
        } else {
            aId.setValue(value);
            if (aId.isModified()) {
                setModified(true);
            }
        }
    }
    
    public void setId(Long value) {
        aId.setValue(value);
        if (aId.isModified()) {
            setModified(true);
        }
    }
    
    public void setId(Object value) {
        aId.setValue(value);
        if (aId.isModified()) {
            setModified(true);
        }
    }
    
    public void nullifyId() {
        if (!aId.isNull()) {
            aId.setNull(true);
            setModified(true);
        }
    }
    
    public DomId getId() {
        return aId;
    }
    
    public DomId oldId() {
        return oId;
    }
    
    public Long valueOfId() {
        return aId.getValue();
    }
    
    public boolean isIdModified() {
        return aId.isModified();
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Atributo OPERACAO_ID">
    
    public EntOperacoesFuncoes operacaoId(Long value) {
        setOperacaoId(value);
        return this;
    }
    
    public void setOperacaoId(DomId value) {
        if (value == null || value.isNull()) {
            nullifyOperacaoId();
        } else {
            aOperacaoId.setValue(value.getValue());
            if (aOperacaoId.isModified()) {
                setModified(true);
            }
        }
    }
    
    public void setOperacaoId(String value) {
        if (value == null) {
            nullifyOperacaoId();
        } else {
            aOperacaoId.setValue(value);
            if (aOperacaoId.isModified()) {
                setModified(true);
            }
        }
    }
    
    public void setOperacaoId(Long value) {
        aOperacaoId.setValue(value);
        if (aOperacaoId.isModified()) {
            setModified(true);
        }
    }
    
    public void setOperacaoId(Object value) {
        aOperacaoId.setValue(value);
        if (aOperacaoId.isModified()) {
            setModified(true);
        }
    }
    
    public void nullifyOperacaoId() {
        if (!aOperacaoId.isNull()) {
            aOperacaoId.setNull(true);
            setModified(true);
        }
    }
    
    public DomId getOperacaoId() {
        return aOperacaoId;
    }
    
    public DomId oldOperacaoId() {
        return oOperacaoId;
    }
    
    public Long valueOfOperacaoId() {
        return aOperacaoId.getValue();
    }
    
    public boolean isOperacaoIdModified() {
        return aOperacaoId.isModified();
    }
    // </editor-fold>
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="getErrors">
    /**
     * Traduz um erro recebido do banco de dados para um AdsException
     */
    @Override
    public AdsException getErrors(String errorMsg, int transaction) {
        AdsException e;
        String msg = errorMsg.toUpperCase();
        
        if (transaction == DELETE_TRANSACTION) {
            e = new AdsException("RTSYSINF.OPERACOES_FUNCOES.GET_ERRORS_UNKNOWN",
                    AdsException.UNKNOWN,
                    "Erro não esperado: " + errorMsg);
        } else {
            if (msg.indexOf("UK_OPEFUN_OPERACAO_FUNCAO") >= 0) {
                e = new AdsException("RTSYSINF.OPERACOES_FUNCOES.UK_OPEFUN_OPERACAO_FUNCAO", 
                        Severity.ERROR,
                        "Registro duplicado! Esta operação já está cadastrada para esta função! Operação ${OPERACAO_ID}, Funcao ${FUNCAO_ID} (UK_OPEFUN_OPERACAO_FUNCAO)");
                return e;
            } else if (msg.indexOf("FK_FUNCAO_OPERACAO") >= 0) {
                e = new AdsException("RTSYSINF.OPERACOES_FUNCOES.FK_FUNCAO_OPERACAO", 
                        Severity.ERROR,
                        "Registro não cadastrado para FUNCAO! (FK_FUNCAO_OPERACAO)");
                return e;
            } else if (msg.indexOf("FK_OPERACAO") >= 0) {
                e = new AdsException("RTSYSINF.OPERACOES_FUNCOES.FK_OPERACAO", 
                        Severity.ERROR,
                        "Registro não cadastrado para OPERACAO! (FK_OPERACAO)");
                return e;
            } else if (msg.indexOf("PK_OPEFUN") >= 0) {
                e = new AdsException("RTSYSINF.OPERACOES_FUNCOES.PK_OPEFUN", 
                        Severity.ERROR,
                        "ID duplicado! (PK_OPEFUN)");
                return e;
            } else {
                e = new AdsException("RTSYSINF.OPERACOES_FUNCOES.GET_ERRORS_UNKNOWN",
                        AdsException.UNKNOWN,
                        "Erro não esperado: " + errorMsg);
            }
        }
        return e;
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Entity Information">
    
    public String getEntityName() {
        return ENTITY_NAME;
    }
    
    public String getTableName() {
        return TABLE_NAME;
    }
    
    public String idSequenceName() {
        return "PK_SEQUENCE";
    }
    
    private ArrayList<Field> allAttributes;
    public ArrayList<Field> getAllAttributes() {
        if (allAttributes == null) {
            allAttributes = new ArrayList<Field>();
            allAttributes.add(aFuncaoId);
            allAttributes.add(aId);
            allAttributes.add(aOperacaoId);
        }
        return allAttributes;
    }
    
    /**
     * Retorna o valor da primeira UK da entidade
     * Se ela for composta, retorna a concatenação de toda a combinação
     * de atributos separados por um espaço.
     */
    public String valueOfUk() {
        return getOperacaoId().toString() +
                " " + getFuncaoId().toString();
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Relationships">
    
    /**
     * Métodos de manipulação dos IDs das entidades associadas
     */
    public DomId getAssociationId1() {
        return getOperacaoId();
    }
    public DomId getAssociationId2() {
        return getFuncaoId();
    }
    public void setAssociationId1(long id) {
        setOperacaoId(id);
    }
    public void setAssociationId2(long id) {
        setFuncaoId(id);
    }
    
    public void findByOperacaoIdFuncaoId(long operacaoId, long funcaoId) throws AdsException {
        findBy(new String[] {"OPERACAO_ID", "FUNCAO_ID"},
                new Object[] {operacaoId, funcaoId});
    }
    
    private EntFuncoesSistemas eFuncao;
    
    public EntFuncoesSistemas findFuncao() throws AdsException {
        if (getFuncaoId().isNull()) {
            return null;
        }
        if (eFuncao == null || !valueOfFuncaoId().equals(eFuncao.valueOfId())) {
            eFuncao = new EntFuncoesSistemas(ctx);
            eFuncao.find(valueOfFuncaoId());
        }
        return eFuncao;
    }
    
    /**
     * Ativa o join desta entidade com FUNCOES_SISTEMAS
     * através do atributo FUNCAO_ID
     */
    public EntFuncoesSistemas joinFuncao() {
        return joinFuncao(null);
    }
    public EntFuncoesSistemas joinFuncao(String alias) {
        EntFuncoesSistemas entity = new EntFuncoesSistemas(ctx);
        if (alias != null) {
            entity.setAlias(alias);
        }
        Join newJoin = new Join(getFuncaoId(), entity);
        entity.setJoinedBy(newJoin);
        this.join(newJoin);
        return entity;
    }
    
    public void findByFuncao(long id, String sqlAppend) throws AdsException {
        find("select ID from OPERACOES_FUNCOES where FUNCAO_ID = ? " + sqlAppend);
        sqlSetLong(1,id);
    }
    
    public void findByFuncao(long id) throws AdsException {
        findByFuncao(id,"");
    }
    
    public void findByFuncao(Entity entidade) throws AdsException {
        findByFuncao(entidade.valueOfId(),"");
    }
    
    public void findByFuncao(Entity entidade, String sqlAppend) throws AdsException {
        findByFuncao(entidade.valueOfId(),sqlAppend);
    }
    
    private EntOperacoesSistemas eOperacao;
    
    public EntOperacoesSistemas findOperacao() throws AdsException {
        if (getOperacaoId().isNull()) {
            return null;
        }
        if (eOperacao == null || !valueOfOperacaoId().equals(eOperacao.valueOfId())) {
            eOperacao = new EntOperacoesSistemas(ctx);
            eOperacao.find(valueOfOperacaoId());
        }
        return eOperacao;
    }
    
    /**
     * Ativa o join desta entidade com OPERACOES_SISTEMAS
     * através do atributo OPERACAO_ID
     */
    public EntOperacoesSistemas joinOperacao() {
        return joinOperacao(null);
    }
    public EntOperacoesSistemas joinOperacao(String alias) {
        EntOperacoesSistemas entity = new EntOperacoesSistemas(ctx);
        if (alias != null) {
            entity.setAlias(alias);
        }
        Join newJoin = new Join(getOperacaoId(), entity);
        entity.setJoinedBy(newJoin);
        this.join(newJoin);
        return entity;
    }
    
    public void findByOperacao(long id, String sqlAppend) throws AdsException {
        find("select ID from OPERACOES_FUNCOES where OPERACAO_ID = ? " + sqlAppend);
        sqlSetLong(1,id);
    }
    
    public void findByOperacao(long id) throws AdsException {
        findByOperacao(id,"");
    }
    
    public void findByOperacao(Entity entidade) throws AdsException {
        findByOperacao(entidade.valueOfId(),"");
    }
    
    public void findByOperacao(Entity entidade, String sqlAppend) throws AdsException {
        findByOperacao(entidade.valueOfId(),sqlAppend);
    }
    
    /**
     * Limpa os objetos normalizados da entidade
     */
    public void clearRelatedObjects() {
        eFuncao = null;
        eOperacao = null;
    }
    
    /**
     * Método que copia os valores dos atributos
     * para os valores respectivos old 
     */
    public void saveOldAtributes() {
        oFuncaoId.setValue(aFuncaoId);
        oId.setValue(aId);
        oOperacaoId.setValue(aOperacaoId);
    }
    
    /**
     * Método que retorna as regras da entidade
     * @return ArrayList com as regras ou null caso não existir nenhuma regra
     */
    public ArrayList getAllRules() {
        ArrayList<EntityRule> out = new ArrayList<EntityRule>();
        {
            UniqueKeyRule rule = new UniqueKeyRule();
            rule.setEntity(EntOperacoesFuncoes.class);
            rule.setName("UK_OPEFUN_OPERACAO_FUNCAO");
            rule.addAttribute(new DomId("OPERACAO_ID",""));
            rule.addAttribute(new DomId("FUNCAO_ID",""));
            out.add(rule);
        }
        {
            PrimaryKeyRule rule = new PrimaryKeyRule();
            rule.setEntity(EntOperacoesFuncoes.class);
            rule.setName("PK_OPEFUN");
            rule.setPkAttribute(new DomId("ID",""));
            out.add(rule);
        }
        {
            ForeignKeyRule rule = new ForeignKeyRule();
            rule.setEntity(EntOperacoesFuncoes.class);
            rule.setAssociatedEntity(EntOperacoesSistemas.class);
            rule.setName("FK_OPERACAO");
            rule.addAttribute(new DomId("OPERACAO_ID",""));
            out.add(rule);
        }
        {
            ForeignKeyRule rule = new ForeignKeyRule();
            rule.setEntity(EntOperacoesFuncoes.class);
            rule.setAssociatedEntity(EntFuncoesSistemas.class);
            rule.setName("FK_FUNCAO_OPERACAO");
            rule.addAttribute(new DomId("FUNCAO_ID",""));
            out.add(rule);
        }
        return out;
    }
    // </editor-fold>
    
    @Override
    protected void posInsert() throws AdsException {
        createInterfaceFuncao(); //Garantir um relacionamento entre função e interface
    }
    
    @Override
    protected void posUpdate() throws AdsException {
        createInterfaceFuncao(); //Garantir um relacionamento entre função e interface
    }
    
    @Override
    protected void posDelete() throws AdsException {
        createInterfaceFuncao(); //Garantir um relacionamento entre função e interface
    }
    
    @Override
    public void fillDefaultValues() throws AdsException {
        if (aId.isNull()) {
            aId.setValue("" + ctx.getNextVal("pk_sequence"));
        }
    }
    
    // <editor-fold defaultstate="collapsed" desc="Métodos customizados">
    
    /**
     * Regra de ação: Garantir um relacionamento entre função e interface
     * 
     * Garantir que o que está informado nas interfaces da função, está 
     * coerente com o que está informado nesta entidade.
     * Ou seja, sempre que estiver inserindo um novo registro, deve-se 
     * garantir que existe registro mapeando o respectivo relacionamento 
     * entre função e interface. Por outro lado, sempre que estiver excluindo 
     * um registro, deve-se garantir que, caso não exista mais nenhum outro 
     * relacionamento entre esta função e uma operação desta interface, que 
     * seja excluído também o relacionamento entre a interface e a função.
     */
    private void createInterfaceFuncao() throws AdsException {
        // <user-code id="241581" parentId="241572" hashcode="231104ab" length="1349">
        EntOperacoesSistemas operSist = findOperacao();
        if (operSist.getInterfaceId().isNotNull()) {
            if (currentTransaction == DELETE_TRANSACTION) {
                // Se não tiver mais nenhum, deve excluir interfaces-funcoes
                int count = Integer.parseInt(ads.computeSqlValue("select count(1)" +
                        " from operacoes_funcoes opfu" +
                        " join operacoes_sistemas opsi on opsi.id = opfu.operacao_id" +
                        " where opfu.funcao_id = " + valueOfFuncaoId() +
                        " and opsi.interface_id = " + operSist.valueOfInterfaceId()));
                if (count == 0) {
                    EntInterfacesFuncoes intfFunc = new EntInterfacesFuncoes(ads);
                    intfFunc.del("select id from interfaces_funcoes" +
                            " where funcao_id = " + valueOfFuncaoId() +
                            " and interface_id = " + operSist.valueOfInterfaceId());
                }
            } else {
                // Inserindo ou alterando
                EntInterfacesFuncoes intfFunc = new EntInterfacesFuncoes(ads);
                try {
                    intfFunc.findByFuncaoIdInterfaceId(valueOfFuncaoId(),operSist.valueOfInterfaceId());
                } catch (RecordNotFoundException ex) {
                    intfFunc.setFuncaoId(valueOfFuncaoId());
                    intfFunc.setInterfaceId(operSist.valueOfInterfaceId());
                    intfFunc.ins();
                }
            }
        }
        
        // </user-code>
    }
}
